package cc.siyecao.mapper.provider.aspect;

import cc.siyecao.mapper.provider.annotation.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.PageObjectUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class PageAspect {
    /**
     * 定义切入点：对要拦截的方法进行定义与限制，如包、类
     * <p>
     * 1、execution(public * *(..)) 任意的公共方法
     * 2、execution（* set*（..）） 以set开头的所有的方法
     * 3、execution（* com.lingyejun.annotation.LoggerApply.*（..））com.lingyejun.annotation.LoggerApply这个类里的所有的方法
     * 4、execution（* com.lingyejun.annotation.*.*（..））com.lingyejun.annotation包下的所有的类的所有的方法
     * 5、execution（* com.lingyejun.annotation..*.*（..））com.lingyejun.annotation包及子包下所有的类的所有的方法
     * 6、execution(* com.lingyejun.annotation..*.*(String,?,Long)) com.lingyejun.annotation包及子包下所有的类的有三个参数，第一个参数为String类型，第二个参数为任意类型，第三个参数为Long类型的方法
     * 7、execution(@annotation(com.lingyejun.annotation.Lingyejun))
     */
    @Pointcut("@annotation(cc.siyecao.mapper.provider.annotation.Page)")
    private void pageMethod() {

    }

    /**
     * 环绕通知：灵活自由的在目标方法中切入代码
     */
    @Around("pageMethod()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法传入参数
        Object[] params = joinPoint.getArgs();
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        // 反射获取目标类
        Class<?> targetClass = joinPoint.getTarget().getClass();
        // 拿到方法对应的参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        // 根据类、方法、参数类型（重载）获取到方法的具体信息
        Method objMethod = targetClass.getMethod( methodName, parameterTypes );
        // 拿到方法定义的注解信息,分页参数注入
        if (objMethod.isAnnotationPresent( Page.class )) {
            for (int i = 0; i < params.length; i++) {
                com.github.pagehelper.Page page = PageObjectUtil.getPageFromObject( params[i], false );
                if (page != null) {
                    PageHelper.startPage( page.getPageNum(), page.getPageSize() );
                    break;
                }
            }
        }
        // 执行源方法
        Object obj = joinPoint.proceed();
        // 执行结束，清空分页信息
        PageHelper.clearPage();
        return obj;
    }
}
